_require local "../../../extensions/format-utils/main/SmlppgUtil.ppg.smi"
(* _require local "../../../compilerIRs/recordcalc/main/RecordCalc.ppg.smi" *)

_require "../../../../smlformat-lib.smi"
_require "../../../../basis.smi"
_require "../../../libs/ids/main/LocalID.smi"
_require "../../../data/symbols/main/Loc.smi"
_require "../../../data/symbols/main/RecordLabel.smi"
_require local "../../../libs/util/main/TermFormat.smi"
_require "../../../data/runtimetypes/main/FFIAttributes.ppg.smi"
_require "../../../data/runtimetypes/main/RuntimeTypes.ppg.smi"
_require "../../../data/name/main/CodeLabel.smi"
_require "../../../data/name/main/ExternSymbol.smi"
_require "../../../data/types/main/Types.ppg.smi"
_require "../../../data/builtin/main/BuiltinPrimitive.ppg.smi"
_require "../../../compilerIRs/absyn/main/ConstFormat.smi"


structure RuntimeCalc =
struct
  type loc = Loc.loc
  type ty = Types.ty * RuntimeTypes.ty
  type primInfo =
      {
        primitive : BuiltinPrimitive.primitiveRuntimeCalc,
        ty : {boundtvars : Types.btvEnv,
              argTyList : Types.ty list,
              resultTy : Types.ty}
      }
  type varInfo = {id: VarID.id, ty: ty}
  datatype ncconst =
      NVINT8 of Int8.int
    | NVINT16 of Int16.int
    | NVINT32 of Int32.int
    | NVINT64 of Int64.int
    | NVWORD8 of Word8.word
    | NVWORD16 of Word16.word
    | NVWORD32 of Word32.word
    | NVWORD64 of Word64.word
    | NVCONTAG of Word32.word
    | NVREAL64 of Real64.real
    | NVREAL32 of Real32.real
    | NVCHAR of Char.char
    | NVUNIT
    | NVNULLPOINTER
    | NVNULLBOXED
    | NVTAG of {tag : RuntimeTypes.tag, ty : Types.ty}
    | NVSIZE of {size : RuntimeTypes.size, ty : Types.ty}
    | NVFOREIGNSYMBOL of
      {
        name : string,
        ty : ty
      }
    | NVFUNENTRY of FunEntryLabel.id
    | NVEXFUNENTRY of ExternFunSymbol.id
    | NVCALLBACKENTRY of CallbackEntryLabel.id
    | NVTOPDATA of DataLabel.id
    | NVEXTRADATA of ExtraDataLabel.id
    | NVCAST of
      {
        value : ncconst,
        valueTy : ty,
        targetTy : ty,
        cast : BuiltinPrimitive.cast
      }
  datatype ncexp =
      NCFOREIGNAPPLY of
      {
        funExp : ncexp,
        argExpList : ncexp list,
        attributes : FFIAttributes.attributes,
        resultTy : ty option,
        loc : loc
      }
    | NCEXPORTCALLBACK of
      {
        codeExp : ncexp,
        closureEnvExp : ncexp,
        instTyvars : Types.btvEnv,
        resultTy : ty,
        loc : loc
      }
    | NCCONST of {const: ncconst, ty: ty, loc: loc}
    | NCINTINF of {srcLabel: ExtraDataLabel.id, loc: loc}
    | NCVAR of {varInfo : varInfo, loc : loc}
    | NCEXVAR of
      {
        id : ExternSymbol.id,
        ty : ty,
        loc : loc
      }
    | NCPACK of
      {
        exp : ncexp,
        expTy : ty,
        loc : loc
      }
    | NCUNPACK of
      {
        exp : ncexp,
        resultTy : ty,
        loc : loc
      }
    | NCDUP of
      {
        srcAddr : address,
        resultTy : ty,
        valueSize : ncexp,
        loc : loc
      }
    | NCCOPY of
      {
        srcExp : ncexp,
        dstAddr : address,
        valueSize : ncexp,
        loc : loc
      }
    | NCSTORE of
      {
        srcExp : ncexp,
        srcTy : ty,
        dstAddr : address,
        loc : loc
      }
    | NCLOAD of
      {
        srcAddr : address,
        resultTy : ty,
        loc : loc
      }
    | NCPRIMAPPLY of
      {
        primInfo : primInfo,
        argExpList : ncexp list,
        argTyList : ty list,
        resultTy : ty,
        instTyList : ty list,
        instTagList : ncexp list,
        instSizeList : ncexp list,
        loc : loc
      }
    | NCCALL of
      {
        codeExp : ncexp,
        closureEnvExp : ncexp option,
        argExpList : ncexp list,
        resultTy : ty,
        loc : loc
      }
    | NCLET of
      {
        boundVar: varInfo,
	boundExp: ncexp,
        mainExp : ncexp,
        loc : loc
      }
    | NCRECORD of
      {
        fieldList : {fieldExp : initField,
                     fieldTy : ty,
                     fieldIndex : ncexp} list,
        recordTy : ty,
        isMutable : bool,
        clearPad : bool,
        allocSizeExp : ncexp,
        bitmaps : {bitmapIndex : ncexp,
                   bitmapExp : ncexp} list,
        loc : loc
      }
    | NCMODIFY of
      {
        recordExp : ncexp,
        recordTy : ty,
        indexExp : ncexp,
        valueExp : initField,
        valueTy : ty,
        loc : loc
      }
    | NCRAISE of
      {
        argExp : ncexp,
        resultTy : ty,
        loc : loc
      }
    | NCHANDLE of
      {
        tryExp : ncexp,
        exnVar : varInfo,
        handlerExp : ncexp,
	resultTy : ty,
        loc : loc
      }
    | NCSWITCH of
      {
        switchExp : ncexp,
        expTy : ty,
        branches : {constant : ncconst, branchExp : ncexp} list,
        defaultExp : ncexp,
	resultTy : ty,
        loc : loc
      }
    | NCCATCH of
      {
        catchLabel : FunLocalLabel.id,
        argVarList : varInfo list,
        catchExp : ncexp,
        tryExp : ncexp,
        resultTy : ty,
        loc : loc
      }
    | NCTHROW of
      {
        catchLabel : FunLocalLabel.id,
        argExpList : ncexp list,
        resultTy : ty,
        loc : loc
      }
    | NCCAST of
      {
        exp : ncexp,
        expTy : ty,
        targetTy : ty,
        cast : BuiltinPrimitive.cast,
        loc : loc
      }
    | NCEXPORTVAR of
      {
        id : ExternSymbol.id,
        ty : ty,
        valueExp : ncexp,
        loc : loc
      }
  and address =
      NAPTR of ncexp
    | NARECORDFIELD of
      {
        recordExp : ncexp,
        fieldIndex : ncexp
      }
    | NAARRAYELEM of
      {
        arrayExp : ncexp,
        elemSize : ncexp,
        elemIndex : ncexp
      }
  and initField =
      INIT_CONST of ncconst * ty
    | INIT_VALUE of varInfo
    | INIT_COPY of {srcExp: varInfo, fieldSize: varInfo}
    | INIT_IF of {tagExp: varInfo, tagOfTy: Types.ty,
                  ifBoxed: initField, ifUnboxed: initField}
  type topconst = ncconst * ty
  datatype topdata =
      NTEXTERNVAR of
      {
        id : ExternSymbol.id,
        ty : ty,
        provider : Types.provider,
        loc : loc
      }
    | NTEXPORTVAR of
      {
        id : ExternSymbol.id,
        weak : bool,
        ty : ty,
        value : topconst option,
        loc : loc
      }
    | NTEXTERNFUN of
      {
        id : ExternFunSymbol.id,
        tyvars : Types.btvEnv,
        argTyList : ty list,
        retTy : ty,
        provider : Types.provider,
        loc : loc
      }
    | NTEXPORTFUN of
      {
        id : ExternFunSymbol.id,
        funId : FunEntryLabel.id,
        loc : loc
      }
    | NTSTRING of
      {
        id : DataLabel.id,
        string : string,
        loc : loc
      }
    | NTINTINF of
      {
        id : ExtraDataLabel.id,
        value : IntInf.int,
        loc : loc
      }
    | NTRECORD of
      {
        id : DataLabel.id,
        tyvarKindEnv : Types.btvEnv,
        fieldList : {fieldExp : topconst,
                     fieldSize : topconst,
                     fieldIndex : topconst} list,
        recordTy : Types.ty,
        isMutable : bool,
        isCoalescable : bool,
        clearPad : bool,
        bitmaps : {bitmapIndex : topconst,
                   bitmapExp : topconst} list,
        loc : loc
      }
    | NTARRAY of
      {
        id : DataLabel.id,
        elemTy : ty,
        isMutable : bool,
        isCoalescable : bool,
        clearPad : bool,
        numElements : topconst,
        initialElements : topconst list,
        elemSizeExp : topconst,
        tagExp : topconst,
        loc : loc
      }

  datatype topdec =
      NTFUNCTION of
      {
        id : FunEntryLabel.id,
        tyvarKindEnv : Types.btvEnv,
        argVarList : varInfo list,
        closureEnvVar : varInfo option,
        bodyExp : ncexp,
        retTy : ty,
        gcCheck : bool,
        loc : loc
      }
    | NTCALLBACKFUNCTION of
      {
        id : CallbackEntryLabel.id,
        tyvarKindEnv : Types.btvEnv,
        argVarList : varInfo list,
        closureEnvVar : varInfo option,
        bodyExp : ncexp,
        attributes : FFIAttributes.attributes,
        retTy : ty option,
        loc : loc
      }
  type program =
      {
        topdata : topdata list,
        topdecs : topdec list,
        topExp : ncexp
      }

  val format_ty
      : ty -> SMLFormat.FormatExpression.expression list
  val formatWithType_ty
      : ty -> SMLFormat.FormatExpression.expression list
  val format_primInfo
      : primInfo -> SMLFormat.FormatExpression.expression list
  val formatWithType_primInfo
      : primInfo -> SMLFormat.FormatExpression.expression list
  val format_varInfo
      : varInfo -> SMLFormat.FormatExpression.expression list
  val formatWithType_varInfo
      : varInfo -> SMLFormat.FormatExpression.expression list
  val format_ncconst : ncconst -> SMLFormat.FormatExpression.expression list
  val formatWithType_ncconst
      : ncconst -> SMLFormat.FormatExpression.expression list
  val format_ncexp : ncexp -> SMLFormat.FormatExpression.expression list
  val format_address : address -> SMLFormat.FormatExpression.expression list
  val format_initField : initField -> SMLFormat.FormatExpression.expression list
  val format_topdata : topdata -> SMLFormat.FormatExpression.expression list
  val formatWithType_topdata
      : topdata -> SMLFormat.FormatExpression.expression list
  val format_topdec : topdec -> SMLFormat.FormatExpression.expression list
  val format_program : program -> SMLFormat.FormatExpression.expression list
  val formatWithType_program
      : program -> SMLFormat.FormatExpression.expression list

end
